package com.ddone.ioc.demo.service;

import com.alibaba.druid.pool.DruidDataSource;
import com.ddone.ioc.demo.bean.Address;
import com.ddone.ioc.demo.bean.City;
import com.ddone.ioc.demo.bean.Employ;
import com.ddone.ioc.demo.bean.User;
import com.ddone.ioc.demo.dao.impl.UserDaoImpl;
import com.ddone.ioc.demo.service.impl.BookServiceImpl;
import com.ddone.ioc.demo.service.impl.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * @author ddone
 * @date 2024/3/19-12:58
 */
@Slf4j
public class BeanTest {
    ClassPathXmlApplicationContext context;

    @Before
    public void init() {
        //1.创建一个容器对象 设置配置文件
        /*
         * BeanFactory
         * ApplicationContext
         *
         * 实现：
         *   ClassPathXmlApplicationContext 选择这具体的容器
         *   FileSystemXmlApplicationContext
         *   WebApplicationContext
         */
        /*
         * 创建对象时，直接将ioc的配置给容器对象！
         * 这样容器对象就只要进行哪些ioc动作！
         * [IOC]
         */

        context = new ClassPathXmlApplicationContext("application-anno.xml");
    }

    @After
    public void destroy(){
        // 3. 关闭容器对象
        context.close();
    }
    @Test
    public void testGetBean() {
        //2.读取容器对象中存储的user和address [DI]
        User user = (User) context.getBean("user");
        System.out.println("user = " + user);
        log.info("=========================");
        Address address = (Address) context.getBean("address");
        System.out.println("address = " + address);
    }

    @Test
    public void testServiceBean(){
        /*
         *
         * TODO: 三种方式应该如何选择使用
         *       第一种方式需要强转，不推荐！
         *       第二三种方式，不需要强转， 推荐！
         *       第二种： 对应ioc容器中，只会有一个类型对象！ 如果是接口，只有一个实现类！
         *       第三种： 还是根据id获取，自动帮助强转！ 任何场景都适应！
         *
         *       TODO：接口只有一个实现类，推荐第二种！
         *             接口有多个实现类，推荐第三种！
         *
         * TODO: getBean(class类型能不能写成接口)
         *       IOC容器中， 一定放的实现类对象！
         *       获取的时候，能不能根据接口获取！
         *       ！！！可以！！！
         *
         * TODO：接口
         *       自动找到接口在ioc容器的实现！
         */
        /*
         * 直接根据bean id 获取！
         * 返回的类型是Object需要自己强转
         */
        UserService userService = (UserService) context.getBean("userService");
        System.out.println("userService = " + userService);
        /*
         * 根据类型获取！
         *   类.class
         * 返回的类型，是指定的类型
         * NoUniqueBeanDefinitionException: No qualifying bean
         */
        UserService userService1 = context.getBean(UserServiceImpl.class);
        System.out.println("userService1 = " + userService1);

        /*
         * 根据bean id获取，并且自动将返回值转成对应class类型
         * 返回值类型：指定的结果类型
         */
        UserService userService2 = context.getBean("userService", UserService.class);
        System.out.println("userService2 = " + userService2);
    }

    @Test
    public void testGetDataSource() throws SQLException {
        DataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
        System.out.println("dataSource = " + dataSource);
        Connection connection = dataSource.getConnection();
        System.out.println("connection = " + connection);
    }

    @Test
    public void testCollection(){
        Employ employ = context.getBean("employ", Employ.class);
        System.out.println("employ = " + employ);
    }

    @Test
    public void testService(){
        UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class);
        System.out.println("userService = " + userService);
        UserDaoImpl userDao = context.getBean("userDao", UserDaoImpl.class);
        System.out.println("userDao = " + userDao);
    }

    @Test
    public void testBeanList(){
        List<City> cityList = (List<City>) context.getBean("cityList");
        System.out.println("cityList = " + cityList);
    }
    @Test
    public void testAnnoService(){
        BookService bookService = context.getBean("bookService", BookServiceImpl.class);
        System.out.println("bookService = " + bookService);
    }
}
